package clientmgl;






import java.awt.Color;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JPanel;

import constants.*;

import objects.SpetialFeature;
import objects.WorldObject;





public class ClientMGL extends JPanel{

	
	
	
	static final String HOST = "localhost"; 
	static final int PUERTO=4999; //puerto en el cual recibe el servidor
	Socket skCliente;             //socket mediante el cual me conecto al servidor 
	DataInputStream flujoEntrada; 
	DataOutputStream flujoSalida;
	
	MainFrame frame = null;


	int idCliente;

	private int mouseX;
	private int mouseY;
	
	private ArrayList<WorldObject> objectList = new ArrayList();
	private ArrayList<WorldObject> backgroundList = new ArrayList();
	private WorldObject backgroundObject=null;
	private int state = Constants.WAIT_FOR_ACTION;
	private int dx=0,dy=0;
	private int x=0,y=0;
	
	 
	String agentName = null;
	
	int objectID=-1;
	
	PopUpInteraction popUp = new PopUpInteraction();
	
	//Inventory inventory;
	private int height;
	private int width;
	private boolean clearScreen = false;
	
	
	public ClientMGL(DataInputStream dataInput , DataOutputStream dataOutput, int clientId, MainFrame frame){

		idCliente=clientId;
		
		flujoEntrada= dataInput;
		flujoSalida = dataOutput;
		addMouseListener(new mouseListener());
		addMouseMotionListener(new mouseMotionListener());
		//inventory = null;
		this.frame=frame;
	
		
		
	}
	
	@Override
	public void paint(Graphics g) {
		
		Graphics2D g2d = (Graphics2D) g;
		AffineTransform prev = g2d.getTransform();
		AffineTransform at =prev;
		
		if((mouseX)>=frame.getWidth()-Constants.BORDER_TO_MOVE_PANEL){
			if((frame.getWidth()-dx-Constants.MOVE_PANEL_SPEED)<=width+Constants.INVENTORY_WIDTH){
			//	System.out.println("estoy yendo a la derecha");
				dx=dx-Constants.MOVE_PANEL_SPEED;
			}
			
		}
		if(mouseX<Constants.BORDER_TO_MOVE_PANEL){
			if((dx+Constants.MOVE_PANEL_SPEED)<=0){
			//	System.out.println("estoy yendo a la izquierda");
				dx=dx+Constants.MOVE_PANEL_SPEED;
			}
		}
		//PARA LAS Y
		
		if((mouseY)>=frame.getHeight()-Constants.BORDER_TO_MOVE_PANEL){
			if((frame.getHeight()-dy-Constants.MOVE_PANEL_SPEED)<=height){
			//	System.out.println("estoy yendo hacia arriba");
				dy=dy-Constants.MOVE_PANEL_SPEED;
			}
			
		}
		if(mouseY<Constants.BORDER_TO_MOVE_PANEL){
			if((dy+Constants.MOVE_PANEL_SPEED)<=0){
			//	System.out.println("estoy yendo hacia abajo");
				dy=dy+Constants.MOVE_PANEL_SPEED;
			}
		}
		
				
		at=AffineTransform.getTranslateInstance(dx+Constants.INVENTORY_WIDTH,dy);
		g2d.setTransform(at);

		
		if(clearScreen){
			g.clearRect(0, 0, 1000, 1000);
			clearScreen=false;
		}
		
		
		paintBackground(g);
		Object objArrayList[] = objectList.toArray();
		
		for(int i=0;i<objArrayList.length;i++){
			WorldObject w = (WorldObject) objArrayList[i];
			drawLife(w,g);
			g.drawImage(w.getImageObject().getImageToShow(),(int)w.getImageObject().getPosition().getX(),(int)w.getImageObject().getPosition().getY(),null);
			drawBlueCircle(g,w);
			if(w.getObjectReference()==ReferenceObject.OBJECT_REFERENCE_COMMAND_CENTER1 && w.getOwner()==idCliente){
				SpetialFeature minerals = w.getFeature(ReferenceSpecialFeature.SPETIAL_FEATURE_MINERAL_QUANTITY);
				if(minerals==null){continue;}
				g.drawString("MIN"+minerals.getValue(), (int)w.getImageObject().getPosition().getX(),(int) w.getImageObject().getPosition().getY()-5);
			}
			if(w.getObjectReference()==ReferenceObject.OBJECT_REFERENCE_COMMAND_CENTER1 && w.getOwner()==idCliente){
				SpetialFeature minerals = w.getFeature(ReferenceSpecialFeature.SPETIAL_FEATURE_VESPENE_GAS_QUANTITY);
				if(minerals==null){continue;}
				g.drawString("GAS"+minerals.getValue(), (int)w.getImageObject().getPosition().getX()+75,(int) w.getImageObject().getPosition().getY());
			}
		}
		
		
		if(!frame.getParametersStack().isEmpty()){
			g.setColor(Color.WHITE);
			if(frame.getParametersStack().peek().equals(constants.Constants.PARAMETER_OBJECT)){
				g.drawString("Object", mouseX-dx, mouseY-dy);
			}
			if(frame.getParametersStack().peek().equals(constants.Constants.PARAMETER_POSITION)){
				g.drawString("Position", mouseX-dx, mouseY-dy);
			}
			g.setColor(Color.black);
			System.out.println("pinte");
		}
		
		g2d.setTransform(prev);
		
	}

	

	private void drawBlueCircle(Graphics g, WorldObject w) {
		
		if(w.getOwner()!=idCliente){
			return;
		}
		double radio = (w.getImageObject().getImageToShow().getWidth()*0.30);
		double x = (w.getImageObject().getPosition().getX()+w.getImageObject().getImageToShow().getWidth()/2)-radio/2;
		double y = (w.getImageObject().getPosition().getY()+w.getImageObject().getImageToShow().getHeight()/2)-radio/2;
		g.setColor(Color.BLUE);
		g.fillOval((int)x,(int)y,(int)radio,(int)radio);
		g.setColor(Color.black);
		
	}

	private void drawLife(WorldObject object, Graphics g) {
		double currentLife=0;
		double totalLife=0;
		
		Object featureList [] = object.getListFeatures().toArray(); 
		
		for(int i=0;i<featureList.length;i++){
			SpetialFeature feature = (SpetialFeature) featureList[i];
			if(feature.getId()==ReferenceSpecialFeature.SPETIAL_FEATURE_LIFE){
				totalLife=feature.getValue();
			}
			if(feature.getId()==ReferenceSpecialFeature.SPETIAL_FEATURE_CURRENT_LIFE){
				currentLife=feature.getValue();
			}
		}
		
		if(totalLife==0){
			return;
		}
		int greenBar = (int)((currentLife*object.getImageObject().getImageToShow().getWidth())/totalLife);
		
		g.setColor(Color.red);
		g.fillRect((int)object.getImageObject().getPosition().getX(),(int)object.getImageObject().getPosition().getY()-10, object.getImageObject().getImageToShow().getWidth(), 5);
		
		g.setColor(Color.green);
		g.fillRect((int)object.getImageObject().getPosition().getX(),(int)object.getImageObject().getPosition().getY()-10, greenBar, 5);
		
		g.setColor(Color.black);
		
	}

	private void paintBackground(Graphics g) {
		if (backgroundObject==null) {
			return;
		}
		int imageWidth=backgroundObject.getImageObject().getImageToShow().getWidth();
		int imageHeight=backgroundObject.getImageObject().getImageToShow().getHeight();
		for(int i =0;i<width;i=i+imageWidth){
			for(int j = 0 ; j< height; j=j+imageHeight){
				g.drawImage(backgroundObject.getImageObject().getImageToShow(),i,j,null);
			}
		}
		for (WorldObject obj : backgroundList){
			g.drawImage(obj.getImageObject().getImageToShow(),(int)obj.getPosition().getX(),(int) obj.getPosition().getY(), null);
		}
		
	}

	private class mouseMotionListener implements MouseMotionListener{

		@Override
		public void mouseDragged(MouseEvent ev) {
			proccesMouseClicks(ev);
			//System.out.println("Estoy dragged");
		}

		@Override
		public void mouseMoved(MouseEvent ev) {
			mouseX=ev.getX();
			mouseY=ev.getY();
			
		}
		
	}

	private class mouseListener implements MouseListener{

		@Override
		public void mouseClicked(MouseEvent ev) {
			proccesMouseClicks(ev);
			
			}
		
		@Override
		public void mouseEntered(MouseEvent e) {
			
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			System.out.println("sali");
			mouseX=frame.getWidth()/2;
			mouseY=frame.getHeight()/2;
			
		}

		@Override
		public void mousePressed(MouseEvent ev) {
			
			
		}

		@Override
		public void mouseReleased(MouseEvent ev) {
			proccesMouseClicks(ev);
			System.out.println("Estoy Releaed");
			
		}
		
	}
	
	public void generatePopUp(String[] splt) {
		objectID=getObjectID(x,y);
		frame.generatePopUp(splt,mouseX,mouseY,objectID);

		
		
		
	}
	
	

	public void generateObjects(String[] splt){
		double time=System.currentTimeMillis();
		//System.out.println("T1:"+time);
		objectList= new ArrayList();
		backgroundList= new ArrayList();
		for(int i=1;i<splt.length;i++){
			WorldObject obj = MainFrame.createObject(splt[i]);
			if(obj.getIsBackground()==constants.Constants.TRUE){
				backgroundList.add(obj);
			}
			else{
				objectList.add(MainFrame.createObject(splt[i]));
			}
		}
		
		for(WorldObject w: objectList){
			w.getImageObject().setImageToShow(ImagesSingleton.images[w.getObjectReference()]);
			//w.getImageObject().setMini(ImagesSingleton.imagesMini[w.getObjectReference()]);
			//System.out.println("cree un objeto en la inventorya "+w.getImageObject().getImageToShow().getWidth());
		}
		
		
		Collections.sort(objectList);
	}
	
	
	
	
	
	public void addPositionToParameterMessage(int x, int y) {
		//parametersMessage= parametersMessage+"/"+x+";"+y;
		frame.setParametersMessage(frame.getParametersMessage()+"/"+x+";"+y);
		
	}


	public void addObjectIdToParameterMessage(int x, int y) {
		for(WorldObject obj : objectList){
			if(x >obj.getImageObject().getPosition().getX() && y >obj.getImageObject().getPosition().getY() && 
					x <obj.getImageObject().getPosition().getX()+obj.getImageObject().getImageToShow().getWidth() &&
					y< obj.getImageObject().getPosition().getY()+obj.getImageObject().getImageToShow().getHeight())
			{
				
				System.out.println("ENCONTRE EL OBJETOOOOOOOOO "+obj.getID());
				//parametersMessage=parametersMessage+"/"+obj.getID();
				frame.setParametersMessage(frame.getParametersMessage()+"/"+obj.getID());
				return;
			}
			
		}
		System.out.println("NO HAY OBJETO SELECCIONADO");
		frame.getParametersStack().push(constants.Constants.PARAMETER_OBJECT);
		
	}
	

	public void sendParametersToAgent() {
		System.out.println("Tengo todos los parametros para enviar al agente ");
		//System.out.println(parametersMessage);
		try {
			flujoSalida.writeUTF(frame.getParametersMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void sendAgentChosed(String str) {
		try {
		String s = new String();
		agentName=str;
		 s = Message.ASK_FOR_PARAMETERS+System.getProperty("line.separator")+objectID+";"+str;
		 
		
		flujoSalida.writeUTF(s);
		
		System.out.println(s);
		System.out.println("SELECCIONE "+str);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	public int getObjectID(int x, int y) {
		int idToReturn=constants.Constants.NO_OBJECT_ID; 
		for(WorldObject obj : objectList){
			if(x >obj.getImageObject().getPosition().getX() && y >obj.getImageObject().getPosition().getY() && 
					x <obj.getImageObject().getPosition().getX()+obj.getImageObject().getImageToShow().getWidth() &&
					y< obj.getImageObject().getPosition().getY()+obj.getImageObject().getImageToShow().getHeight())
			{
				idToReturn =  obj.getID();
				if(obj.getOwner()==idCliente){
					return idToReturn;
				}
			}
			
		}
		return idToReturn;
	}
	
	
	
	/*public Inventory getInventory() {
		return inventory;
	}

	public void setInventory(Inventory inventory) {
		this.inventory = inventory;
	}*/

	public void requestInventoryFromObject() {
		objectID = getObjectID(x, y);
		String message = new String();
		System.out.println("este es el id client "+objectID);
		message=Message.REQUEST_INVENTORY+System.getProperty("line.separator")+objectID;
		frame.setObjectInventoryId(objectID);
		try {
			flujoSalida.writeUTF(message);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setState(int state) {
		this.state=state;
		
	}

	public WorldObject getBackgroundObject() {
		return backgroundObject;
	}

	public void setBackgroundObject(String[] splt) {
		
		
			
		backgroundObject = (MainFrame.createObject(splt[1]));
		
		backgroundObject.getImageObject().setImageToShow(ImagesSingleton.images[backgroundObject.getObjectReference()]);
		
		String size [] = splt[2].split(";");
		height = Integer.parseInt(size[0]);
		width = Integer.parseInt(size[1]);
		
		System.out.println("height "+height+" width "+width);
		
	}
	
	private void proccesMouseClicks(MouseEvent ev) {
		x=ev.getX()-dx;
		y=ev.getY()-dy;
		
			switch(state){
			case Constants.WAIT_FOR_ACTION:
				if(ev.getButton() == MouseEvent.BUTTON3){
					//System.out.println("Click izquierdo");
				//	WorldObject obj = world.clickObject(ev.getX()-dx,ev.getY()-dy);
					try {
						int idObject =getObjectID(x, y);
						String msg = Message.ASK_FOR_ACTION_FROM_OBJECT+System.getProperty("line.separator")+idObject;
						frame.setObjectInventoryId(idObject);
						
						flujoSalida.writeUTF(msg);
						System.out.println(msg);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(ev.getButton() == MouseEvent.BUTTON1){
					
					requestInventoryFromObject();
				}
				
			break;
			case Constants.PARAMETERS_FOR_ACTION:
			
				
				if(ev.getButton() == MouseEvent.BUTTON3){
					frame.setState(Constants.WAIT_FOR_ACTION);
					System.out.println("NO DOY PARAMETROS A LA ACCION");
					return;
				}
				System.out.println("Asigno Parametro");
				/*if(frame.getParametersStack().isEmpty()){
					sendParametersToAgent();
					state=Constants.WAIT_FOR_ACTION;
					return;
				}*/
				switch (frame.getParametersStack().pop()){
				case constants.Constants.PARAMETER_OBJECT:
					addObjectIdToParameterMessage(x,y);
				break;
				case constants.Constants.PARAMETER_POSITION:
					addPositionToParameterMessage(x,y);
				break;
				}
				if(frame.getParametersStack().isEmpty()){
					frame.setState(Constants.WAIT_FOR_ACTION);
					
					sendParametersToAgent();
				}
			//	setParameter(ev.getX()-dx, ev.getY()-dy);
			break;
			}
	
		
	}

	public void setCameraPosition(double x2, double y2) {
		dx=(int)-x2;
		dy=(int)-y2;
		
		dx=dx+frame.getWidth()/2;
		dy=dy+frame.getHeight()/2;
		
		if(dx>0){
			dx=0;
		}
		if(dy>0){
			dy=0;
		}
		
	}

	public void clearScreen() {
		clearScreen =true;
		
	}
	
}